﻿using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

/// <summary>
/// UI拖拽组件
/// </summary>
public class UIDragComponent : UIBehaviour, IPointerDownHandler, IDragHandler
{
    [Tooltip("限制移动范围")]
    public bool isClampInCanvas = true;

    [Tooltip("允许范围")]
    public List<RectTransform> legalDragAreas;

    // 父节点,这个最好是UI父节点，因为它的矩形大小刚好是屏幕大小
    private RectTransform _ParentRectTransform = null;
    private RectTransform m_ParentRectTransform => _ParentRectTransform ?? (_ParentRectTransform = rectTransform.parent as RectTransform);


    private Vector2 m_MouseStartPos;
    private Vector3 m_UIStartPos;
    private bool isLegalDrag = false;

    // 鼠标按下
    public void OnPointerDown(PointerEventData data)
    {
        if (!IsInLegalDrag(data.position))
        {
            isLegalDrag = false;
            return;
        }
        isLegalDrag = true;

        // 记录当前面板起点
        m_UIStartPos = rectTransform.localPosition;
        // 通过屏幕中的鼠标点，获取在父节点中的鼠标点
        RectTransformUtility.ScreenPointToLocalPointInRectangle(m_ParentRectTransform, data.position, data.pressEventCamera, out m_MouseStartPos);
    }

    // 拖动
    public void OnDrag(PointerEventData data)
    {
        if (rectTransform == null || m_ParentRectTransform == null)
        {
            return;
        }
        if (!isLegalDrag)
        {
            return;
        }
        // 获取本地鼠标位置
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_ParentRectTransform, data.position, data.pressEventCamera, out Vector2 localPointerPosition))
        {
            // 移动位置 = 本地鼠标当前位置 - 本地鼠标起点位置
            Vector3 offsetToOriginal = localPointerPosition - m_MouseStartPos;
            // 当前面板位置 = 面板起点 + 移动位置
            rectTransform.localPosition = m_UIStartPos + offsetToOriginal;
        }
        // 限制拖动范围
        if (isClampInCanvas)
        {
            ClampToWindow();
        }
    }

    // 限制当前面板在父节点中的区域位置
    private void ClampToWindow()
    {
        // 面板位置
        Vector3 pos = rectTransform.localPosition;

        // 如果是UI父节点，设置面板大小为0，那么最大最小位置为正负屏幕的一半
        Vector3 minPosition = m_ParentRectTransform.rect.min - rectTransform.rect.min;
        Vector3 maxPosition = m_ParentRectTransform.rect.max - rectTransform.rect.max;

        pos.x = Mathf.Clamp(rectTransform.localPosition.x, minPosition.x, maxPosition.x);
        pos.y = Mathf.Clamp(rectTransform.localPosition.y, minPosition.y, maxPosition.y);

        rectTransform.localPosition = pos;
    }

    // 判断是否在允许拖拽的范围内拖拽
    private bool IsInLegalDrag(Vector3 pos)
    {
        if (legalDragAreas.Count <= 0)
        {
            return false;
        }
        foreach (var trans in legalDragAreas)
        {
            if (trans.position.x + trans.rect.min.x <= pos.x &&
                trans.position.x + trans.rect.max.x >= pos.x &&
                trans.position.y + trans.rect.min.y <= pos.y &&
                trans.position.y + trans.rect.max.y >= pos.y)
            {
                return true;
            }
        }
        return false;
    }
}